package com.learning.server.design;

/**
 * 总体来说，工厂模式适合：凡是出现了大量的产品需要创建，并且具有共同的接口时，可以通过工厂方法模式进行创建。
 * 在以上的三种模式中，第一种如果传入的字符串有误，不能正确创建对象，第三种相对于第二种，不需要实例化工厂类，
 * 所以，大多数情况下，我们会选用第三种——静态工厂方法模式。
 *
 * 工厂方法模式有一个问题就是，类的创建依赖工厂类，也就是说，如果想要拓展程序，必须对工厂类进行修改，这违背了
 * 闭包原则，所以，从设计角度考虑，有一定的问题，如何解决？就用到抽象工厂模式，创建多个工厂类，这样一旦需要增
 * 加新的功能，直接增加新的工厂类就可以了，不需要修改之前的代码。因为抽象工厂不太好理解，我们先看看图，然后就
 * 和代码，就比较容易理解。
 */


//普通工厂方法模式

interface Sender {
    public void Send();
}


class MailSender implements Sender {
    @Override
    public void Send() {
        System.out.println("this is mail sender!");
    }
}

class SmsSender implements Sender {

    @Override
    public void Send() {
        System.out.println("this is sms sender!");
    }
}


//抽象工厂模式（Abstract Factory）

interface Provider {
    public Sender produce();
}

class SendMailFactory implements Provider {

    @Override
    public Sender produce(){
        return new MailSender();
    }
}

class SendSmsFactory implements Provider{

    @Override
    public Sender produce() {
        return new SmsSender();
    }
}


public class Factory {

    //普通方法
    public Sender produce(String type) {
        if ("mail".equals(type)) {
            return new MailSender();
        } else if ("sms".equals(type)) {
            return new SmsSender();
        } else {
            System.out.println("请输入正确的类型!");
            return null;
        }
    }


    //多个工厂方法模式
    public Sender produceMail(){
        return new MailSender();
    }

    public Sender produceSms(){
        return new SmsSender();
    }


    //静态方法
    public static Sender produceMail2(){
        return new MailSender();
    }

    public static Sender produceSms2(){
        return new SmsSender();
    }

    public static void main(String[] args) {
        //普通工厂方法模式
        Factory factory = new Factory();
        Sender sender = factory.produce("sms");
        sender.Send();

        //多个工厂方法模式
        Sender sender2 = factory.produceMail();
        sender2.Send();

        //静态方法
        Sender sender3 = Factory.produceMail2();
        sender3.Send();

        //抽象工厂模式（Abstract Factory）
        Provider provider = new SendMailFactory();
        Sender sender4 = provider.produce();
        sender4.Send();
    }
}
